﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UniRlv.Utility.AppLib
{
    public abstract class AbtInDevice
    {
        public abstract bool Open();
        public abstract bool IsOpen();
        public abstract void Close();
        public abstract void Pause();
        public abstract void Resume();
        public abstract void SendData(byte[] bytes, int len);

        public event EventHandler<EventArgs> DataReceived;

        protected string _initString;
        public abstract string InitString { get; set; }
        public string ErrorString { get; set; }
        public int Prefix { get; set; }
        public string Suffix { get; set; }

        protected List<byte> prcBuff;//字节队列
        protected Queue<string> dataQueue;//数据队列
        protected object lockObj = new object();

        /// <summary>
        /// 字节处理函数，用于生成数据
        /// </summary>
        /// <returns></returns>
        protected virtual bool ByteProccess()
        {
            int idx = 0;
            int endPos = -1;//第一帧结束位置
            string sType;

            lock (lockObj)
            {
                if (prcBuff.Count() < (Prefix + Suffix.Length + 1))//剔除时，数据帧长度为1
                {
                    return false;
                }
                else if (Prefix + Suffix.Length > 0)
                {
                    for (idx = Prefix; idx <= prcBuff.Count - Suffix.Length; idx++)
                    {

                        if (ByteCmpFromIdx(Encoding.Default.GetBytes(Suffix), prcBuff.ToArray(), idx))
                        {
                            endPos = idx;
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                else
                {
                    sType = ReturnType(prcBuff.ToArray(), prcBuff.Count);
                    dataQueue.Enqueue(Encoding.GetEncoding(sType).GetString(prcBuff.ToArray(), 0, prcBuff.Count));
                    prcBuff.Clear();
                    return true;
                }

                if (endPos<0)
                {//no ound
                    return false;
                }

                ///gb2312和utf8自适应
                byte[] arr = prcBuff.ToArray();
                sType = ReturnType(arr, endPos - Prefix, Prefix);
                dataQueue.Enqueue(Encoding.GetEncoding(sType).GetString(arr, Prefix, endPos - Prefix));
                prcBuff.RemoveRange(0, endPos + Suffix.Length);
            }


            return true;
        }

        /// <summary>
        /// 字节数组比较，用于查找缓存中是否包含后缀
        /// </summary>
        /// <param name="suffix">后缀数组</param>
        /// <param name="buff">缓存</param>
        /// <param name="skip">跳过字节</param>
        /// <returns></returns>
        private bool ByteCmpFromIdx(byte[] suffix, byte[] buff, int skip)
        {
            bool res = true;

            for (int i = 0; i < suffix.Length; i++ )
            {
                if (suffix[i]!=buff[skip+i])
                {
                    res = false;
                    break;
                }
            }

            return res;
        }

        public virtual bool IfHasData()
        {
            return dataQueue.Count > 0;
        }

        public virtual string GetData()
        {
            if (this.IfHasData())
            {
                return dataQueue.Dequeue();
            }
            else
            {
                return null;
            }
        }

        public virtual void SendData(string s)
        {
            byte[] bytes = Encoding.GetEncoding("GBK").GetBytes(s);
            SendData(bytes, bytes.Length);
        }

        protected void SetEvent(EventArgs e)
        {
            if (DataReceived!=null)
            {
                DataReceived(this, e);
            }
        }


        /// <summary>
        /// 返回字节数组的字符编码
        /// </summary>
        /// <param name="checkByte">字节数组</param>
        /// <param name="cnt">字节数量</param>
        /// <param name="skip">跳过字节数</param>
        /// <returns>字符编码字符串表示</returns>
        protected string ReturnType(byte[] checkByte, int cnt, int skip=0)
        {
            string tempStr = Encoding.UTF8.GetString(checkByte, skip, cnt);
            byte[] tempByte = Encoding.UTF8.GetBytes(tempStr);

            if (JudgeEqual(checkByte, tempByte, cnt, skip))
            {
                return "UTF-8";
            }
            else
            {
                return "GBK";
            }
        }

        /// <summary>
        /// 字节数组比对
        /// </summary>
        /// <param name="bt1">数组1</param>
        /// <param name="bt2">数组2</param>
        /// <param name="cnt">比对字节数量</param>
        /// <param name="skip1">数组1跳过字节数</param>
        /// <param name="skip2">数组2跳过字节数</param>
        /// <returns>比对的字节是否一样</returns>
        protected bool JudgeEqual(byte[] bt1, byte[] bt2, int cnt, int skip1=0, int skip2=0)
        {
            bool b = true;

            for (int i = 0; i < cnt; i++)
            {
                if (bt1[skip1+i] != bt2[skip2+i])
                {
                    b = false;
                }
            }

            return b;
        }
    }
}
